package com.kongchengji.zhanguafou.service;

import com.kongchengji.zhanguafou.constant.WxInfo;
import com.kongchengji.zhanguafou.dao.QuartzDAO;
import com.kongchengji.zhanguafou.dao.ServerDAO;
import com.kongchengji.zhanguafou.domain.QuartzDO;
import com.kongchengji.zhanguafou.domain.Result;
import com.kongchengji.zhanguafou.domain.ServerDO;
import com.kongchengji.zhanguafou.utils.BuildCustomerMsgUtil;
import com.kongchengji.zhanguafou.utils.FormatTimeUtil;
import com.kongchengji.zhanguafou.utils.PingServerUtil;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class ServerService {
    @Autowired
    private ServerDAO serverDAO;
    @Autowired
    JobService jobService;
    @Autowired
    private QuartzDAO quartzDAO;
    /**
     * 校验ip的合法性
     * @param ip 服务器ip
     * @return
     */
    public Result ValidateIp(String ip) {
        Map map = PingServerUtil.pingServer(ip);
        if (map.get("time") == null) {
            return Result.error("不存在该ip,请输入正确的ip");
        }
        return null;
    }


    public Result saveConfig(ServerDO serverDO){
        QuartzDO quartzDO = buildQuartz(serverDO,"com.kongchengji.zhanguafou.quartz.ListenServerScheduleTask");
        //判断ip的合法性
        Result result = ValidateIp(serverDO.getIp());
        if(result != null){
            return result;
        }
        //通过jobName判断任务是否存在数据库,不在将任务保存数据库
        Example example = new Example(QuartzDO.class);
        example.createCriteria().andEqualTo("jobName",quartzDO.getJobName());
        int count = quartzDAO.selectCountByExample(example);
        if(count != 0){
            return Result.error("该服务器已添加,如果未启动请直接在监控列表中启动");
        }
        //将服务器的信息添加到数据库
        serverDAO.insertSelective(serverDO);
        //将任务信息保存于数据库
        quartzDAO.insertSelective(quartzDO);
        jobService.save(quartzDO);
        return Result.ok("添加监控成功");
    }






    /**
     * 根据时间表达式构造quartz对象，并将quartz对象和server对象保存数据库
     * @param serverDO 监控对象
     * @param clazz 实际执行的任务类
     * @return
     */
    private QuartzDO buildQuartz(ServerDO serverDO,String clazz){
        //根据用户所选的时间组成cron表达式
        String cron = "0 0/"+serverDO.getInterval()+" * * * ?";
        QuartzDO quartz = new QuartzDO();
        //组成任务的唯一标识
        quartz.setJobName("Ping"+ serverDO.getIp() + serverDO.getOpenId());
        quartz.setJobGroup("Ping");
        quartz.setDescription("测试服务器是否可连接");
        quartz.setJobClassName(clazz);
        quartz.setOpenId(serverDO.getOpenId());
        quartz.setUrl(serverDO.getIp());
        quartz.setCronExpression(cron);
        return quartz;
    }



    /**
     * 根据规则返回匹配的结果
     *
     * @param line  匹配的内容
     * @param regex 匹配的规则
     * @return 返回匹配结果
     */
    private String matchLine(String line, String regex) {
        Pattern pattern = Pattern.compile(regex);
        Matcher m = pattern.matcher(line);
        if (m.find()) {
            return m.group();
        }
        return null;
    }

    /**
     * 查询用户监控的服务器信息
     *
     * @param map 微信带过来信息封装成map
     * @return 构造微信需要的xml数据
     */
    public String selecServert(Map map) {
        String toUserName = (String) map.get("ToUserName");
        String openId = (String) map.get("FromUserName");
        Example example = new Example(QuartzDO.class);
        example.createCriteria().andEqualTo("openId", openId).andEqualTo("jobGroup","Ping");
        List<QuartzDO> quartzDOS = quartzDAO.selectByExample(example);
        String defaultMessage = "客官别急,正在查询,请稍等";
        if (quartzDOS.size() == 0) {
            defaultMessage = "你还未添加监控,请先添加";
        } else {
            StringBuilder stringBuilder = new StringBuilder();
            //耗时操作,如果5秒内微信服务器得不到响应会重试,并在公众号中出现提供的服务出现故障的提示,所以异步执行。
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (QuartzDO quartzDO : quartzDOS) {
                        //调用系统命令获得结果
                        Map<String, String> serverMap = PingServerUtil.pingServer(quartzDO.getUrl());
                        //构造Content内容
                        stringBuilder.append(
                                "服务器ip:" + quartzDO.getUrl() + "\n" +
                                        "丢包率:" + serverMap.get("lossRation") + "\n" +
                                        "最小时间/平均时间/最大时间/算术平均差" + serverMap.get("time") + "\n");
                    }
                    String contentJson = BuildCustomerMsgUtil.buildMessage(stringBuilder.toString(), openId);
                    RequestBody requestBody =
                            FormBody.create(MediaType.parse("application/json;charset=utf-8"), contentJson);
                    Request request = new Request
                            .Builder()
                            .url("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + WxInfo.accessToken.getToken())
                            .post(requestBody)
                            .build();
                    OkHttpClient okHttpClient = new OkHttpClient();
                    try {
                        okHttpClient.newCall(request).execute();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

            });
            t.start();
        }
        String result = String
                .format(
                        "<xml>" +
                                "<ToUserName><![CDATA[%s]]></ToUserName>" +
                                "<FromUserName><![CDATA[%s]]></FromUserName>" +
                                "<CreateTime>%s</CreateTime>" +
                                "<MsgType><![CDATA[text]]></MsgType>" +
                                "<Content><![CDATA[%s]]></Content>" +
                                "</xml>",
                        openId, toUserName, FormatTimeUtil.getFormatTime(),
                        defaultMessage);
        return result;
    }

}
